/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package appGUI;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.imageio.*;
import javax.swing.*;
import mainApp.Data;
import mainApp.Difficulty;
import utils.DataAdapter;
import utils.Utils;

/**
 *
 * @author Picto
 */
public class MainPanel extends JPanel implements MouseListener, KeyListener, Runnable {

    JButton button;
    InputStream fontLocation;
    InputStream lcdFrameLocation;
    Graphics g;
    Font font;
    Utils utility;
    private BufferedImage lcdFrame;
    boolean textBoxFocus;
    Thread animateTextFocus;
    Thread animationLoop;
    boolean underscoreOnOff;
    ArrayList<Character> guessWord;
    JLabel inputLabel;
    DataAdapter dataAdapter;
    Data data;
    LetterGrid lg;
    boolean isInitialised;
    boolean incorrectGuess;
    int animationLooper;
    int lcdFrameIter;

    public MainPanel() {
        fontLocation = this.getClass().getResourceAsStream("/appGUI/resources/DS-DIGI.TTF");
        lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-0.png");
        utility = new Utils();
        textBoxFocus = false;
        underscoreOnOff = false;
        guessWord = new ArrayList<Character>();
        inputLabel = new JLabel();
        dataAdapter = new DataAdapter();
        isInitialised = false;
        lg = new LetterGrid();
        incorrectGuess = false;
        animationLooper = 0;
        lcdFrameIter = 0;
    }

    public void initialise(Data d) {
        data = d;
        this.add(inputLabel);
        this.add(lg);
        addMouseListener(this);
        inputLabel.addKeyListener(this);
        animationLoop = new Thread(this);
        animationLoop.start();
        char[] dst = new char[20];
        data.getWord().getValue().getChars(0, data.getWord().getWordLength(), dst, 0);
        for (int i = 0; i <= data.getWord().getWordLength() - 1; i++) {
            data.addInWordArray(dst[i]);
            data.addInWordComparisonArray(' ');
        }
        isInitialised = true;
        try {
            BufferedImage bi = ImageIO.read(ImageIO.createImageInputStream(lcdFrameLocation));
            lcdFrame = bi;
        } catch (IOException e) {
        }
        try {
            font = Font.createFont(Font.TRUETYPE_FONT, fontLocation);
            font = font.deriveFont(50f);
        } catch (FontFormatException ex) {
            Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MainPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        if (isInitialised == true) {
            super.paintComponent(g);
            lg.repaint();
            setBackground(Color.BLACK);
            lg.setBounds(595, 199, 251, 161);
            lg.repaint();
            g.setFont(font);
            g.setColor(Color.GREEN);
            g.drawString("HANGMAN", 410, 50);
            g.drawImage(lcdFrame, 20, 200, 450, 450, null);
            g.drawRect(655, 161, (data.getWord().getWordLength() * 15), 20);
            g.setFont(font.deriveFont(26f));
            g.drawString("Click a letter in the grid or type a word into the guess", 190, 80);
            g.drawString("word box to guess at the word. Word attempts cost 5 guesses!", 165, 100);
            g.drawString("Word: ", 20, 180);
            char[] dst = new char[20];
            utility.getWordString(data.getWord(), data.getWordComparisonArray()).getChars(0, data.getWord().getWordLength(), dst, 0);
            for (int i = 0; i <= data.getWord().getWordLength() - 1; i++) {
                if (dst[i] == '_') {
                    g.drawString(String.valueOf(dst[i]), 80 + (i * 15), 177);
                } else {
                    g.drawString(String.valueOf(dst[i]), 80 + (i * 15), 180);
                }
            }
            g.drawRect(19, 161, (60 + (data.getWord().getWordLength() * 15)), 20);
            g.drawRect(19, 199, 452, 452);
            g.drawString("Guess word: ", 515, 180);
            g.drawString("Current Score: " + data.getScore(), 594, 400);
            g.drawString("High Score: " + data.getHighScore().getScore(), 594, 430);
            g.drawString("Guesses Remaining: " + (10 - data.getAttempts()), 594, 460);
            for (int i = 0; i < guessWord.size(); i++) {
                g.drawString(String.valueOf(guessWord.get(i)), 657 + (i * 15), 180);
            }
            if (textBoxFocus == true && underscoreOnOff == true && guessWord.size() < data.getWord().getWordLength()) {
                g.drawString("_", (657 + (guessWord.size() * 15)), 177);
            } else if (textBoxFocus == false && isInitialised == true) {
                animateTextFocus = null;
            }
            if (data.isGuessedCorrectly() == true) {
                g.drawRect(595, 475, 110, 20);
                g.drawString("Next Word", 596, 494);
            }
            g.setFont(font.deriveFont(70f));
            if (incorrectGuess == true && animationLooper <= 40) {
                g.setColor(new Color(0, 255, 0, 255 - (animationLooper * 6)));
                animationLooper += 1;
                g.drawString("Incorrect!", 335, 200 - (animationLooper));
            } else if (data.isGuessedCorrectly() == true && animationLooper <= 40) {
                g.setColor(new Color(0, 255, 0, 255 - (animationLooper * 6)));
                animationLooper += 1;
                g.drawString("Correct!", 360, 200 - animationLooper);
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        System.out.println("Mouse Clicked at: " + e.getX() + ", " + e.getY());
        char letterClicked = utility.getLetterClicked(e);
        inputLabel.requestFocusInWindow();
        //Text Box
        if (data.isGuessedCorrectly() == false && e.getX() > 655 && e.getX() < 655 + (data.getWord().getWordLength() * 15) && e.getY() > 161 && e.getY() < 181) {
            textBoxFocus = true;
            animateTextFocus = new Thread(this);
            animateTextFocus.start();
        } else if (data.isGuessedCorrectly() == true && e.getX() > 595 && e.getX() < 705 && e.getY() > 475 && e.getY() < 495) {
            data.clearAllData();
            lcdFrameIter = 0;
            iterLCDFrame(lcdFrameIter);
            guessWord.clear();
            char[] dst = new char[20];
            data.getWord().getValue().getChars(0, data.getWord().getWordLength(), dst, 0);
            for (int i = 0; i <= data.getWord().getWordLength() - 1; i++) {
                data.addInWordArray(dst[i]);
                data.addInWordComparisonArray(' ');
            }
            data.setAttempts(0);
            data.setGuessedCorrectly(false);
            animationLooper = 0;
            incorrectGuess = false;
            lg.enableAllLetters();
        } else if (letterClicked != ' ' && !data.getLettersAttempted().contains(letterClicked) && data.isGuessedCorrectly() == false) {
            attemptLetter(letterClicked);
            lcdFrameIter++;
            iterLCDFrame(lcdFrameIter);
            lg.disableLetter(String.valueOf(letterClicked));
            textBoxFocus = false;
        } else {
            textBoxFocus = false;
        }
    }

    public void attemptLetter(char in) {
        if (data.isGuessedCorrectly() == false) {
            int counter = 0;
            data.addAttemptedLetter(in);
            for (int i = 0; i <= (data.getWord().getWordLength() - 1); i++) {
                if (data.getWordArray().get(i) == in) {
                    data.setInWordComparisonArray(i, in);
                } else {
                    counter++;
                }
            }
            data.setWordComparisonArray(utility.truncateCharArrayList(data.getWordComparisonArray(), data.getWord().getWordLength()));
            if (counter == (data.getWord().getWordLength())) {
                System.out.println("Incorrect guess, please try again.");
            } else {
                System.out.println("There are " + ((data.getWord().getWordLength()) - counter) + " " + in + "s in the word.");
                if (data.getWordComparisonArray().containsAll(data.getWordArray())) {
                    System.out.println("Congratulations the word was: " + data.getWord().getValue() + "!");
                    if (getDifficulty().equals(Difficulty.EASY)) {
                        data.incrementScore(1);
                    } else if (getDifficulty().equals(Difficulty.MEDIUM)) {
                        data.incrementScore(2);
                    } else {
                        data.incrementScore(3);
                    }
                    data.setGuessedCorrectly(true);
                }
            }
            data.addAttemptedLetter(in);
            data.incrementAttempt();
            if (data.getAttempts() == 10 && data.isGuessedCorrectly() == false) {
                data.setGuessedCorrectly(true);
                incorrectGuess = true;
                data.setScore(0);
                data.setWordComparisonArray(data.getWordArray());
            }
        }
    }

    public Difficulty getDifficulty() {
        if (data.getWord().getWordLength() < 5) {
            return Difficulty.EASY;
        } else if (data.getWord().getWordLength() > 8) {
            return Difficulty.HARD;
        } else if (data.getWord().getWordLength() >= 5 & data.getWord().getWordLength() <= 8) {
            return Difficulty.MEDIUM;
        } else {
            return Difficulty.ERROR_OUT_OF_RANGE;
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void run() {
        while (animateTextFocus == Thread.currentThread()) {
            if (underscoreOnOff == true) {
                underscoreOnOff = false;
            } else {
                underscoreOnOff = true;
            }
            try {
                Thread.sleep(500);
            } catch (Exception e) {
                System.exit(0);
            }
        }
        while (animationLoop == Thread.currentThread()) {
            repaint();
            try {
                Thread.sleep(16);
            } catch (Exception e) {
                System.exit(0);
            }
        }
    }

    public void quit() {
        animateTextFocus = null;
        animationLoop = null;
    }

    @Override
    public void keyTyped(KeyEvent e) {
        if (textBoxFocus == true) {
            Pattern p = Pattern.compile("[a-zA-Z]");
            if (p.matcher(String.valueOf(e.getKeyChar())).matches() && guessWord.size() < data.getWord().getWordLength() && data.isGuessedCorrectly() == false) {
                guessWord.add(Character.toLowerCase(e.getKeyChar()));
            } else if ((e.getKeyChar() == '\b') && !guessWord.isEmpty() && data.isGuessedCorrectly() == false) {
                guessWord.remove(guessWord.size() - 1);
            } else if (e.getKeyChar() == '\n') {
                if (data.isGuessedCorrectly() == false) {
                    if (guessWord.equals(data.getWordArray())) {
                        data.setWordComparisonArray(guessWord);
                        data.setLettersAttempted(guessWord);
                        if (getDifficulty().equals(Difficulty.EASY)) {
                            data.incrementScore(1);
                        } else if (getDifficulty().equals(Difficulty.MEDIUM)) {
                            data.incrementScore(2);
                        } else {
                            data.incrementScore(3);
                        }
                        data.setGuessedCorrectly(true);
                    } else {
                        data.incrementAttemptWord();
                        lcdFrameIter += 5;
                        iterLCDFrame(lcdFrameIter);
                    }
                    if (data.isGuessedCorrectly() == false && data.getAttempts() >= 10) {
                        data.setGuessedCorrectly(true);
                        data.setAttempts(10);
                        textBoxFocus = false;
                        incorrectGuess = true;
                        data.setScore(0);
                        data.setWordComparisonArray(data.getWordArray());
                    }
                }
            }
        } else {
            Pattern p = Pattern.compile("[a-zA-Z]");
            if (p.matcher(String.valueOf(e.getKeyChar())).matches()) {
                attemptLetter(e.getKeyChar());
                lg.disableLetter(String.valueOf(e.getKeyChar()));
                lcdFrameIter++;
                iterLCDFrame(lcdFrameIter);
            }
        }
    }

    public void iterLCDFrame(int iter) {
        switch (iter) {
            case 0:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-0.png");
                break;
            case 1:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-1.png");
                break;
            case 2:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-2.png");
                break;
            case 3:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-3.png");
                break;
            case 4:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-4.png");
                break;
            case 5:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-5.png");
                break;
            case 6:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-6.png");
                break;
            case 7:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-7.png");
                break;
            case 8:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-8.png");
                break;
            case 9:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-9.png");
                break;
            case 10:
                lcdFrameLocation = this.getClass().getResourceAsStream("/appGUI/resources/LCD-FRAME-10.png");
                break;
        }
        try {
            BufferedImage bi = ImageIO.read(ImageIO.createImageInputStream(lcdFrameLocation));
            lcdFrame = bi;
        } catch (IOException e) {
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}
